#include "ptrtestadaptor.h"
#include "errcode.h"
#include <QVariant>

int PtrTestAdaptor::typeId = qRegisterMetaType<PtrTestAdaptor*>("PtrTestAdaptor*");

PtrTestAdaptor::PtrTestAdaptor()
{
    generateDBusObjectName();
    startDBusListener();
}

PtrTestAdaptor::~PtrTestAdaptor()
{
    releaseDBusObjectName();
}

int PtrTestAdaptor::GetStatus(QVariant &timeout, QVariant &LFSResult)
{
    if (timeout.toString().isEmpty() || !timeout.canConvert<int>())
        timeout.setValue((ulong)ULONG_MAX);

    REQUESTID requestId = 0;
    HRESULT hResult = LFSAsyncGetInfo(m_hService, LFS_INF_PTR_STATUS, NULL, LFS_INDEFINITE_WAIT, m_szDBusObjectName, &requestId);
    if (LFS_SUCCESS != hResult)
        return ERR_INVOKE;

    LPLFSRESULT pLFSResult = NULL;
    if (!waitForResult(&pLFSResult, timeout.toInt()))
        return ERR_TIMEOUT;

    hResult = pLFSResult->result;
    if (LFS_SUCCESS == hResult) {
        LPLFSPTRSTATUS pLFSCAMStatus = (LPLFSPTRSTATUS)pLFSResult->buffer;
        formatStatusInfo(pLFSCAMStatus, LFSResult);
    }
    else
        LFSResult.setValue((long)hResult);

    FreeResult(pLFSResult);
    return hResult == LFS_SUCCESS ? ERR_OK : ERR_OTHER;
}

int PtrTestAdaptor::GetCapabilities(QVariant &timeout, QVariant &LFSResult)
{
    if (timeout.toString().isEmpty() || !timeout.canConvert<int>())
        timeout.setValue((ulong)ULONG_MAX);

    REQUESTID requestId = 0;
    HRESULT hResult = LFSAsyncGetInfo(m_hService, LFS_INF_PTR_CAPABILITIES, NULL, LFS_INDEFINITE_WAIT, m_szDBusObjectName, &requestId);
    if (LFS_SUCCESS != hResult)
        return ERR_INVOKE;

    LPLFSRESULT pLFSResult = NULL;
    if (!waitForResult(&pLFSResult, timeout.toInt()))
        return ERR_TIMEOUT;

    hResult = pLFSResult->result;
    if (LFS_SUCCESS == hResult) {
        LPLFSPTRCAPS pLFSPTRCaps = (LPLFSPTRCAPS)pLFSResult->buffer;
        formatCapabilitiesInfo(pLFSPTRCaps, LFSResult);
    }
    else
        LFSResult.setValue((long)hResult);

    FreeResult(pLFSResult);
    return hResult == LFS_SUCCESS ? ERR_OK : ERR_OTHER;
}

int PtrTestAdaptor::PrintRawData(QVariant &szData, QVariant &timeout, QVariant &LFSResult)
{
    if (szData.toString().isEmpty())
        return ERR_PARAM;

    if (timeout.toString().isEmpty() || !timeout.canConvert<int>())
        timeout.setValue((ulong)ULONG_MAX);

    LFSPTRRAWDATA lfsPtrRawData;
    memset(&lfsPtrRawData, 0, sizeof(LFSPTRRAWDATA));
    lfsPtrRawData.input_data = LFS_PTR_NOINPUTDATA;
    lfsPtrRawData.data = (LPBYTE)szData.toString().toLocal8Bit().data();
    lfsPtrRawData.size = szData.toString().toLocal8Bit().length();
    REQUESTID requestId = 0;
    HRESULT hResult = LFSAsyncExecute(m_hService, LFS_CMD_PTR_RAW_DATA, &lfsPtrRawData, LFS_INDEFINITE_WAIT, m_szDBusObjectName, &requestId);
    if (LFS_SUCCESS != hResult)
        return ERR_INVOKE;

    LPLFSRESULT pLFSResult = NULL;
    if (!waitForResult(&pLFSResult, timeout.toInt()))
        return ERR_TIMEOUT;

    hResult = pLFSResult->result;
    LFSResult.setValue((long)hResult);
    FreeResult(pLFSResult);
    return hResult == LFS_SUCCESS ? ERR_OK : ERR_OTHER;
}

void PtrTestAdaptor::formatStatusInfo(LPLFSPTRSTATUS lpStatus, QVariant &szStatusInfo)
{
    DECLARE_STRINGSTREAM;

    BEGIN_GROUP;

    OUTPUT_NAME_VALUE("fwDevice", lpStatus->device);
    OUTPUT_NAME_VALUE("fwMedia", lpStatus->media);
    BEGIN_GROUP_WITH_NAME("fwPaper");
    for (int i = 0; i < LFS_PTR_SUPPLYSIZE; i++) {
        OUTPUT_VALUE(lpStatus->paper[i]);
    }
    END_GROUP;
    OUTPUT_NAME_VALUE("fwToner", lpStatus->toner);
    OUTPUT_NAME_VALUE("fwInk", lpStatus->ink);
    OUTPUT_NAME_VALUE("fwLamp", lpStatus->lamp);
    LPLFSPTRRETRACTBINS* lppRetractBins = lpStatus->retract_bins;
    if (lppRetractBins) {
        BEGIN_GROUP_WITH_NAME("lppRetractBins");
        for (; *lppRetractBins != NULL; lppRetractBins++) {
            LPLFSPTRRETRACTBINS lpRetractBins = *lppRetractBins;
            BEGIN_GROUP;
            OUTPUT_NAME_VALUE("wRetractBin", lpRetractBins->retract_bin);
            OUTPUT_NAME_VALUE("usRetractCount", lpRetractBins->retract_count);
            END_GROUP;
        }
        END_GROUP;
    }
    else {
        OUTPUT_NAME_VALUE("lppRetractBins", "(null)");
    }
    OUTPUT_NAME_VALUE("usMediaOnStacker", lpStatus->media_on_stacker);
    BEGIN_GROUP_WITH_NAME("lpszExtra");
    PARSE_EXTRAINFO(lpStatus->extra);
    END_GROUP;

    END_GROUP;

    GET_STRINGSTREAM_DATA(szStatusInfo);
}

void PtrTestAdaptor::formatCapabilitiesInfo(LPLFSPTRCAPS lpWosaPtrCaps, QVariant &szCapsInfo)
{
    DECLARE_STRINGSTREAM;

    BEGIN_GROUP;

    OUTPUT_NAME_VALUE("wClass", lpWosaPtrCaps->dev_class);
    OUTPUT_NAME_VALUE("fwType", lpWosaPtrCaps->dev_type);
    OUTPUT_NAME_VALUE("bCompound", lpWosaPtrCaps->compound);
    OUTPUT_NAME_VALUE("wResolution", lpWosaPtrCaps->resolution);
    OUTPUT_NAME_VALUE("fwReadForm", lpWosaPtrCaps->read_form);
    OUTPUT_NAME_VALUE("fwWriteForm", lpWosaPtrCaps->write_form);
    OUTPUT_NAME_VALUE("fwExtents", lpWosaPtrCaps->extents);
    OUTPUT_NAME_VALUE("fwControl", lpWosaPtrCaps->control);
    OUTPUT_NAME_VALUE("usMaxMediaOnStacker", lpWosaPtrCaps->max_media_on_stacker);
    OUTPUT_NAME_VALUE("bAcceptMedia", lpWosaPtrCaps->accept_media);
    OUTPUT_NAME_VALUE("bMultiPage", lpWosaPtrCaps->multi_page);
    OUTPUT_NAME_VALUE("fwPaperSources", lpWosaPtrCaps->paper_sources);
    OUTPUT_NAME_VALUE("bMediaTaken", lpWosaPtrCaps->media_taken);
    OUTPUT_NAME_VALUE("usRetractBins", lpWosaPtrCaps->retract_bins);
    if (lpWosaPtrCaps->retract_bins > 0) {
        BEGIN_GROUP_WITH_NAME("lpusMaxRetract");
        for (int i = 0; i < lpWosaPtrCaps->retract_bins; i++)
            OUTPUT_VALUE(lpWosaPtrCaps->max_retract[i]);
        END_GROUP;
    }
    else {
        OUTPUT_NAME_VALUE("lpusMaxRetract", "(null)");
    }
    OUTPUT_NAME_VALUE("fwImageType", lpWosaPtrCaps->image_type);
    OUTPUT_NAME_VALUE("fwFrontImageColorFormat", lpWosaPtrCaps->front_image_color_format);
    OUTPUT_NAME_VALUE("fwBackImageColorFormat", lpWosaPtrCaps->back_image_color_format);
    OUTPUT_NAME_VALUE("fwCodelineFormat", lpWosaPtrCaps->codeline_format);
    OUTPUT_NAME_VALUE("fwImageSource", lpWosaPtrCaps->image_source);
    OUTPUT_NAME_VALUE("fwCharSupport", lpWosaPtrCaps->char_support);
    OUTPUT_NAME_VALUE("bDispensePaper", lpWosaPtrCaps->dispense_paper);
    if (lpWosaPtrCaps->extra) {
        BEGIN_GROUP_WITH_NAME("lpszExtra");
        PARSE_EXTRAINFO(lpWosaPtrCaps->extra);
        END_GROUP;
    }
    else {
        OUTPUT_NAME_VALUE("lpszExtra", "(null)");
    }

    END_GROUP;

    GET_STRINGSTREAM_DATA(szCapsInfo);
}
